//
//  CBPeripheralManager+Rx.swift
//  RXSwiftDemo1
//
//  Created by mac on 2025/2/28.
//

import Foundation
import RxSwift
import RxCocoa
import CoreBluetooth

public class RxCBPeripheralDelegateProxy: DelegateProxy<CBPeripheral, CBPeripheralDelegate>, DelegateProxyType, CBPeripheralDelegate {
    
    public init(peripheral: CBPeripheral) {
        super.init(parentObject: peripheral, delegateProxy: RxCBPeripheralDelegateProxy.self)
    }
    
    public static func registerKnownImplementations() {
        self.register { RxCBPeripheralDelegateProxy(peripheral: $0) }
    }
    
    public static func currentDelegate(for object: CBPeripheral) -> CBPeripheralDelegate? {
        return object.delegate
    }
    
    public static func setCurrentDelegate(_ delegate: CBPeripheralDelegate?, to object: CBPeripheral) {
        object.delegate = delegate
    }
}

extension Reactive where Base: CBPeripheral {
    public var delegate: DelegateProxy<CBPeripheral, CBPeripheralDelegate> {
        return RxCBPeripheralDelegateProxy.proxy(for: base)
    }
    
    // 外设名称更新
    public var peripheralDidUpdateName: Observable<String?> {
        return delegate
            .methodInvoked(#selector(CBPeripheralDelegate.peripheralDidUpdateName(_:)))
            .map { $0[0] as? CBPeripheral }
            .map { $0?.name }
    }
    
    // 外设服务更新
    public var didModifyServices: Observable<[CBService]> {
        return delegate
            .methodInvoked(#selector(CBPeripheralDelegate.peripheral(_:didModifyServices:)))
            .compactMap { $0[1] as? [CBService] }
    }
    
    //更新 RSSI值
    public var peripheralDidUpdateRSSI: Observable<(CBPeripheral,Error)> {
        return delegate
            .methodInvoked(#selector(CBPeripheralDelegate.peripheralDidUpdateRSSI(_:error:)))
            .compactMap({ ($0[1],$0[2]) as? (CBPeripheral,Error) })
    }
    
    // 读取 RSSI 值
    public var didReadRSSI: Observable<(CBPeripheral,NSNumber, Error?)> {
        return delegate
            .methodInvoked(#selector(CBPeripheralDelegate.peripheral(_:didReadRSSI:error:)))
            .compactMap { ($0[0],$0[1], $0[2]) as?(CBPeripheral,NSNumber,Error) }
    }
    
    // 发现服务
    public var didDiscoverServices: Observable<[CBService]> {
        return delegate
            .methodInvoked(#selector(CBPeripheralDelegate.peripheral(_:didDiscoverServices:)))
            .compactMap({ $0[0] as? CBPeripheral })
            .compactMap({ $0.services })
    }
    
    // 发现服务的特征
    public var didDiscoverCharacteristicsForService: Observable<(CBService, [CBCharacteristic]?)> {
        return delegate
            .methodInvoked(#selector(CBPeripheralDelegate.peripheral(_:didDiscoverCharacteristicsFor:error:)))
            .compactMap({element in
                guard let service = element[1] as? CBService else {
                    return nil
                }
                let characteristics = service.characteristics
                return (service, characteristics)
            })
    }
    
    
    // 更新通知状态
    public var didUpdateNotificationState: Observable<(CBCharacteristic, Error?)> {
        return delegate
            .methodInvoked(#selector(CBPeripheralDelegate.peripheral(_:didUpdateNotificationStateFor:error:)))
            .compactMap { ($0[1], $0[2]) as?(CBCharacteristic,Error) }
    }
    
    // 发现描述符
    public var didDiscoverDescriptors: Observable<(CBCharacteristic, [CBDescriptor]?)> {
        return delegate
            .methodInvoked(#selector(CBPeripheralDelegate.peripheral(_:didDiscoverDescriptorsFor:error:)))
            .compactMap { ($0[1] , $0[2]) as? (CBCharacteristic,[CBDescriptor]) }
    }
    
    // 成功读取某个 `Characteristic` 的值时触发
    var didUpdateValueForCharacteristic: Observable<CBCharacteristic> {
        return delegate
            .methodInvoked(NSSelectorFromString("peripheral:didUpdateValueForCharacteristic:error:"))
            .compactMap({ $0[1] as? CBCharacteristic })
    }
    
    // 成功写入某个 `Characteristic` 的值后触发
    var didWriteValueForCharacteristic: Observable<(CBCharacteristic,Error?)> {
        return delegate
            .methodInvoked(NSSelectorFromString("peripheral:didWriteValueForCharacteristic:error:"))
            .compactMap({ ($0[1],$0[2]) as? (CBCharacteristic,Error) })
    }
    
    /// 监听 `didUpdateValueFor descriptor`
    var didUpdateValueForDescriptor: Observable<(CBDescriptor, Error?)> {
        return delegate
            .methodInvoked(NSSelectorFromString("peripheral:didUpdateValueForDescriptor:error:"))
            .compactMap({ ($0[1],$0[2]) as? (CBDescriptor,Error) })
    }
    
}
